Práctica 7: Implementación de un driver sencillo en Linux
En esta práctica nos familiarizaremos con los drivers y cómo se organizan y se implementan en Linux.
Los ficheros para esta práctica están disponibles en el siguiente enlace: ficheros_p7s.tar.gz.
Compilar el módulo de ejemplo “hello.c”. Insertar el módulo en el kernel con el comando sudo insmod hello.ko. Para verificar que el módulo se insertó correctamente, ejecutar el comando lsmod y chequear el “log” del sistema con sudo dmesg o sudo dmesg | tail. En este fichero de “log” se puede encontrar el mensaje que el módulo imprimió con printk() en su función de inicialización. Finalmente, descargar el módulo usando sudo rmmod hello.
sudo insmod hello.ko
lsmod
sudo dmesg
sudo dmesg | tail
printk()
sudo rmmod hello
Compilar el módulo chardev.c, que implementa un driver que gestiona dispositivos de caracteres ficticios. Después de compilarlo, insertar el módulo en el kernel con el comando sudo insmod chardev.ko. Para verificar que el módulo se insertó correctamente, chequear el “log” del sistema con sudo dmesg o sudo dmesg | tail. En este fichero de “log” se puede encontrar el major number asignado a este driver y el comando para crear un fichero de dispositivo gestionado por el driver:
sudo insmod chardev.ko
$ sudo mknod /dev/chardev -m 666 c 248 0
Una vez que el fichero de dispositivo fue creado, podemos leer del driver del dispositivo como sigue:
$ cat /dev/chardev I already told you 0 times Hello world! $ cat /dev/chardev I already told you 1 times Hello world! $ cat /dev/chardev I already told you 2 times Hello world!
Si intentamos escribir en el dispositivo obtendremos un mensaje de error en el terminal o en el fichero de “log”:
$ echo "Hello" > /dev/chardev bash: echo: error de escritura: Operación no permitida
¿Por qué aparece este error?
No obstante, ¡enhorabuena!. El comportamiento del driver es el esperado.
Desarrollar un nuevo driver buffermod.c que gestione un buffer de caracteres con capacidad de 512 bytes, y que permita al usuario tanto consultar, como modificar el contenido de este buffer. El driver debe implementarse como un módulo del kernel que, en tiempo de carga, se registre a sí mismo como un driver de dispositivo de caracteres.
buffermod.c
La interacción con el driver desde espacio de usuario se llevará a cabo mediante un fichero de dispositivo llamado /dev/buffermod. Al escribir una cadena de caracteres en ese fichero especial, la cadena escrita reemplazará el contenido antiguo del buffer de caracteres gestionado por el driver. Asimismo, la lectura de ese fichero especial de caracteres devolverá al usuario el contenido de la última cadena escrita en dicho buffer. Este tipo de interacción se refleja en el siguiente ejemplo de ejecución:
/dev/buffermod
## Cargamos módulo (que suponemos ya compilado). $ sudo insmod buffermod.ko # A partir de aquí suponemos que se ha creado el fichero especial de caracteres con mknod ## El buffer está inicialmente vacío (cadena ""), por lo que la lectura inicial no devuelve ningun byte $ cat /dev/buffermod $ ## Alteración del contenido del buffer $ echo cool_string > /dev/buffermod ## Múltiples lecturas devuelven el mismo valor $ cat /dev/buffermod cool_string $ cat /dev/buffermod cool_string ## Alteración del contenido del buffer y consulta del mismo $ echo cooler string > /dev/buffermod $ cat /dev/buffermod cooler string
Para crear el driver se ha de reutilizar el código del ejemplo chardev.c. También se han de tener en cuenta las siguientes consideraciones:
chardev.c
read
write
open
release
buff
write()
len
copy_from_user()
-EFAULT
cat
off
*off==0
*off>0
chardev